﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
using System.Linq.Expressions;
using System.Linq.Dynamic.Core;
using Abp.Linq.Extensions;
using System.Text;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.Collections.Extensions;
using Abp.Domain.Repositories;
using Magicodes.Admin.SFOrders.Dto;
using Microsoft.EntityFrameworkCore;
using Abp.Domain.Uow;
using Magicodes.Admin.Authorization;
using Abp.Authorization;
using Magicodes.Admin.WULINGAddresss;
using Abp.EntityFrameworkCore.Extensions;
using Castle.Core.Logging;
using System.Collections;
using Microsoft.Extensions.Configuration;
using System.Net;
using System.IO;

namespace Magicodes.Admin.SFOrders
{
    [AbpAuthorize(AppPermissions.Pages_Reception_SystemOrder)]
    public class SFOrderAppService : AppServiceBase, ISFOrderAppService
    {
        private readonly IRepository<WULINGAddress, long> _wulingRepository;
        private readonly IRepository<SFOrder, long> _sfOrderRepository;
        private readonly ILogger _logger;
        private readonly IRepository<SFOrderResult, long> _sfOrderResultrepository;
        private readonly IConfiguration _configurationRoot;
        private readonly IRepository<SFQiaoRouteStatusBack, long> _orderStatusRepository;
        private readonly IRepository<SFQiaoRouteWaybillRoute, string> _routeRepository;
        //private readonly IRepository<SFQiaoRouteStatusBack, long> _statusRepository;

        public SFOrderAppService(IRepository<SFOrder, long> sfOrderRepository, 
            IRepository<WULINGAddress, long>    wulingRepository ,
            IRepository<SFOrderResult, long>  sfOrderResultrepository,
            IConfiguration    configuration,
            IRepository<SFQiaoRouteStatusBack, long>  orderStatusRepository,
            IRepository<SFQiaoRouteWaybillRoute, string>  routeRepository,
        ILogger logger)

        {
            _sfOrderRepository = sfOrderRepository;
            _wulingRepository = wulingRepository;
            _logger = logger;
            _sfOrderResultrepository = sfOrderResultrepository;
            _configurationRoot = configuration;
            _orderStatusRepository = orderStatusRepository;
            _routeRepository = routeRepository;

        }
        public async Task DeleteAsync(EntityDto<long> input)
        {
           await _sfOrderRepository.DeleteAsync(input.Id);
        }

        public async Task<PagedResultDto<SFOrderListDto>> GetPageListAsync(GetSFOrderInput input)
        { 
            var query = _sfOrderRepository.GetAll( )
                 .WhereIf(
                 !string.IsNullOrWhiteSpace(input.ServiceStationCode),
                 u => u.ServiceStationCode.Contains(input.ServiceStationCode)
                 )
                 //.IncludeIf(!string.IsNullOrWhiteSpace(input.ServiceStationCode), o => { return o.Addres; })
                  .AsQueryable();

            var addresss = _wulingRepository.GetAll().ToList();

            
             
            var count = await query.CountAsync();

            if (count == 0)
                return new PagedResultDto<SFOrderListDto>();

            var sfOrders = query
               .OrderBy(input.Sorting)
               .PageBy(input)
               .ToList();

            //订单状态 取运单号
            var orderQuery = _sfOrderResultrepository.GetAll().GroupBy(s =>
            s.OrderId).Select(s => s.OrderByDescending(p => p.CreationTime).Take(1));
            var orderResults = orderQuery.Select(s => s.First()).ToList();

             

            var reList = new List<SFOrderListDto>();
            foreach (var item in sfOrders)
            {
                var orderResult = orderResults.FirstOrDefault(s=>s.OrderId==item.Id);
                var address = ObjectMapper.Map<WULINGAddresss.Dto.AddressListDto>(addresss?.FirstOrDefault(s=>s.ServiceStationCode==item.ServiceStationCode));
                var temp = new SFOrderListDto {
                    Addres = address,
                    ServiceStationCode = item.ServiceStationCode,
                     CompanyName=item.CompanyName,
                      CreationTime=item.CreationTime,
                       DeclaredValue=item.DeclaredValue,
                        ExpressProductType=item.ExpressProductType,
                         Id=item.Id,
                          IndustryOrientedValueAddedServices=item.IndustryOrientedValueAddedServices,
                           MonthlyCardNumber=item.MonthlyCardNumber,
                            Note1=item.Note1,
                             Note2=item.Note2,
                              Note3=item.Note3,
                               NumberOfCases=item.NumberOfCases,
                                PaymentMethod=item.PaymentMethod,
                                 Quantity=item.Quantity,
                                  ShippingNumber=item.ShippingNumber,
                                   Weight=item.Weight,
                                    WhetherComeUndone=item.WhetherComeUndone,
                                     WhetherTheValuation=item.WhetherTheValuation,
                                      AddressCoalescing= address?.ReceiverAddress + address?.ServiceStationCode,
                                       ContentOfConsignment=item.ContentOfConsignment,
                                        WaybillNo= orderResult?.waybillNo


                };
                temp.WaybillNo = orderResults.SingleOrDefault(s => s.OrderId == item.Id)?.waybillNo;
                reList.Add(temp);
            }



           // var sfOrderistDtos = ObjectMapper.Map<IReadOnlyList<SFOrderListDto>>(sfOrders);



            return new PagedResultDto<SFOrderListDto>(
                count,
                reList
                );
        }
        [UnitOfWork]
        public async Task ImportFromExcel(IList<ImportSFOrderInputDto> importSFOrderInputDtos)
        {
            var toAddList = ObjectMapper.Map<List<SFOrder>>(importSFOrderInputDtos);
            
            foreach (var item in toAddList)
            {
                if (string.IsNullOrWhiteSpace(item.ShippingNumber))
                    item.ContentOfConsignment = "汽车配件";
                else
                {
                    item.ContentOfConsignment = item.ShippingNumber;

                }
                item.IsNewOrder = true;
                await _sfOrderRepository.InsertAsync(item);
            }
            
        }

        public Task<string> GetPrintImg(long id )
        {
            var order = _sfOrderRepository.Get(id);

            return Task.FromResult( WayBillPrinterTools(order));
        }

        public Task<string> GetPrintJson(long id) {
            var order = _sfOrderRepository.Get(id);
            String jsonParam = AssemblyParameters(order, true);

            return Task.FromResult(jsonParam) ;
        }
        public Task<string> Print(long id)
        {
            var order = _sfOrderRepository.Get(id);

            return Task.FromResult(WayBillPrinterTools(order, true));
        }

        //[Abp.Domain.Uow.UnitOfWork(IsDisabled = true)]
        public async Task<List<SFOrderRouteListDto>> GetRoutePageListAsync(long orderId)
        {
            if (orderId <= 0) throw new ArgumentException("orderid");
            var query =await _routeRepository.GetAllListAsync(s => s.orderid == orderId+"");

            if (query?.Count == 0) return new List<SFOrderRouteListDto>();
            var list = query.ToList();
            /*
            List<SFOrderRouteListDto> reList = new List<SFOrderRouteListDto>();

            foreach (var item in list)
            {
                var temp = new SFOrderRouteListDto
                {
                    acceptAddress = item.acceptAddress,
                    acceptTime = item.acceptTime,
                    mailno = item.mailno,
                    opCode = item.opCode,
                    orderid = item.orderid,
                    remark = item.remark,
                    ResultId = item.ResultId,
                    Id = item.Id
                };
                reList.Add(temp);
            }
            */

           var reList= ObjectMapper.Map<List<SFOrderRouteListDto>>(list);

            return reList;
        }
        [Abp.Domain.Uow.UnitOfWork(IsDisabled =true)]
        public async Task<SFOrderStateDto> GetOrderStateAsync(long orderId)
        {
            if (orderId <= 0) throw new ArgumentException("orderid");
           
           var item =_orderStatusRepository.FirstOrDefault(s => s.orderNo == orderId + "");
            if (item==null) new SFOrderStateDto();

            var re = ObjectMapper.Map< SFOrderStateDto > (item);

            return re;
        }

        #region 打印
        private string WayBillPrinterTools(SFOrder sFOrder,bool isPrint=false)
        {
            #region url
            /*********2联单**************/
            /**
             * 调用打印机 不弹出窗口 适用于批量打印【二联单】
             */
            String url1 = "http://localhost:4040/sf/waybill/print?type=V2.0_poster_100mm150mm&output=noAlertPrint";
            /**
             * 调用打印机 弹出窗口 可选择份数 适用于单张打印【二联单】
             */
            String url2 = "http://localhost:4040/sf/waybill/print?type=V2.0_poster_100mm150mm&output=print";

            /**
             * 直接输出图片的BASE64编码字符串 可以使用html标签直接转换成图片【二联单】
             */
            String url3 = "http://localhost:4040/sf/waybill/print?type=V2.0_poster_100mm150mm&output=image";


            /*********3联单**************/
            /**
             * 调用打印机 不弹出窗口 适用于批量打印【三联单】
             */
            String url4 = "http://localhost:4040/sf/waybill/print?type=V3.0_poster_100mm210mm&output=noAlertPrint";
            /**
             * 调用打印机 弹出窗口 可选择份数 适用于单张打印【三联单】
             */
            String url5 = "http://localhost:4040/sf/waybill/print?type=V3.0_poster_100mm210mm&output=print";

            /**
             * 直接输出图片的BASE64编码字符串 可以使用html标签直接转换成图片【三联单】
             */
            String url6 = "http://localhost:4040/sf/waybill/print?type=V3.0_poster_100mm210mm&output=image";


            /*********2联150 丰密运单**************/
            /**
             * 调用打印机 不弹出窗口 适用于批量打印【二联单】
             */
            String url7 = "http://localhost:4040/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=noAlertPrint";
            /**
             * 调用打印机 弹出窗口 可选择份数 适用于单张打印【二联单】
             */
            String url8 = "http://localhost:4040/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=print";

            /**
             * 直接输出图片的BASE64编码字符串 可以使用html标签直接转换成图片【二联单】
             */
            String url9 = "http://localhost:4040/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=image";


            /*********3联210 丰密运单**************/
            /**
             * 调用打印机 不弹出窗口 适用于批量打印【三联单】
             */
            String url10 = "http://localhost:4040/sf/waybill/print?type=V3.0.FM_poster_100mm210mm&output=noAlertPrint";
            /**
             * 调用打印机 弹出窗口 可选择份数 适用于单张打印【三联单】
             */
            String url11 = "http://localhost:4040/sf/waybill/print?type=V3.0.FM_poster_100mm210mm&output=print";

            /**
             * 直接输出图片的BASE64编码字符串 可以使用html标签直接转换成图片【三联单】
             */
            String url12 = "http://localhost:4040/sf/waybill/print?type=V3.0.FM_poster_100mm210mm&output=image";
            //String url12 = "http://10.118.65.124:9166/waybill-print-service/sf/waybill/print?type=V2.0.FM_poster_100mm150mm&output=image";

            #endregion

            //根据业务需求确定请求地址 改为从配置文件读取
            var  printUrl =string.Empty;
            if(isPrint)
                printUrl= _configurationRoot.GetSection("SFQiao")["PrintUrl"];
            else
            {
                printUrl = _configurationRoot.GetSection("SFQiao")["GetPrintImgUrl"];

            }
            if (string.IsNullOrWhiteSpace(printUrl))
                printUrl = url9;
            String reqURL = printUrl;

            //组装参数  true设置丰密参数 false 不设置
            String jsonParam = AssemblyParameters(sFOrder, true);//true设置丰密参数 false 不设置

            //var ss = AssemblyParameters22(sFOrder, true);

            _logger.Info("组装参数:" + jsonParam);
            //_logger.Info("组装参数:" + ss);

            //电子面单顶部是否需要logo 
            Boolean notTopLogo = true;//true 不需要  false 需要
            if (reqURL.Contains("V2.0") && notTopLogo)
            {
                reqURL = reqURL.Replace("V2.0", "V2.1");
            }

            if (reqURL.Contains("V3.0") && notTopLogo)
            {
                reqURL = reqURL.Replace("V3.0", "V3.1");
            }



            //发送请求
            String result = postJson(reqURL, jsonParam);

            return result;
            #region MyRegion
            if (result.Contains("\",\""))
            {

                // 如子母单及签回单需要打印两份或者以上
                String[] arr = result.Split("\",\"");

                // 输出图片到本地 支持.jpg、.png格式
                for (int i = 0; i < arr.Length; i++)
                {
                    generateImage(arr[i].ToString(), "D:\\qiaoWaybill201811102-" + i + ".jpg");
                }
            }
            else
            {
                generateImage(result, "D:\\qiaoWaybill201811102-1.jpg");
            }
            #endregion



        }

        //组装参数
        private IList<WaybillDto> GetAssemblyParameters(SFOrder sFOrder, Boolean isFengMi)
        {
            IList<WaybillDto> waybillDtoList = new List<WaybillDto>();
            WaybillDto dto = new WaybillDto();

            //五菱地址库
            var address = _wulingRepository.Single(s => s.ServiceStationCode == sFOrder.ServiceStationCode);
            //下单返回报文信息
            var orderResult = _sfOrderResultrepository.Single(s => s.OrderId == sFOrder.Id);
            //var statusBackInfo = _statusRepository.Single(s=>s.orderNo==sFOrder.Id+"");
            //statusBackInfo.s


            //这个必填 
            dto.appId = _configurationRoot.GetSection("SFQiao")["ClientCode"]; //对应丰桥平台获取的clientCode
            dto.appKey = _configurationRoot.GetSection("SFQiao")["Checkword"]; //对应丰桥平台获取的checkWord


            dto.mailNo = orderResult?.waybillNo;
            //  dto.setMailNo("755123457778,001000000002,001000000003");//子母单方式

            //收件人信息  
            dto.consignerProvince = address.Province;
            dto.consignerCity = address.City;
            dto.consignerCounty = address.District;
            dto.consignerAddress = address.ReceiverAddress; ; //详细地址建议最多30个字  字段过长影响打印效果
            dto.consignerCompany = address.ServiceStationName; ;
            dto.consignerMobile = address.ContactPhoneNumber;
            dto.consignerName = address.Contact;
            dto.consignerShipperCode = address.PostCode;
            dto.consignerTel = address.ServiceStationManagerPhoneNumber;


            //寄件人信息
            dto.deliverProvince = _configurationRoot.GetSection("SFQiao")["j_province"];
            dto.deliverCity = _configurationRoot.GetSection("SFQiao")["j_city"];
            dto.deliverCounty = _configurationRoot.GetSection("SFQiao")["j_county"];
            dto.deliverCompany = _configurationRoot.GetSection("SFQiao")["j_company"];
            dto.deliverAddress = _configurationRoot.GetSection("SFQiao")["j_address"]; //详细地址建议最多30个字  字段过长影响打印效果
            dto.deliverName = _configurationRoot.GetSection("SFQiao")["j_contact"];
            dto.deliverMobile = _configurationRoot.GetSection("SFQiao")["j_mobile"];
            dto.deliverShipperCode = "545000";
            dto.deliverTel = _configurationRoot.GetSection("SFQiao")["j_tel"];


            dto.destCode = orderResult.destCityCode; //目的地代码 参考顺丰地区编号
            dto.zipCode = orderResult.sourceCityCode; //原寄地代码 参考顺丰地区编号

            //签回单号  签单返回服务POD 会打印两份快单 其中第二份作为返寄的单==如有签回单业务需要传此字段值
            //dto.setReturnTrackingNo("755123457778");

            //陆运E标示
            //业务类型为"电商特惠、顺丰特惠、电商专配、陆运件"则必须打印E标识，用以提示中转场分拣为陆运件
            //dto.electric = "E"; by hhg 0129



            //1 ：标准快递   2.顺丰特惠   3： 电商特惠   5：顺丰次晨  6：顺丰即日  7.电商速配   15：生鲜速配	
            #region 快递类型
            var expressType = 0;
            var typeText = sFOrder.ExpressProductType;
            var expressTypes = _configurationRoot.GetSection("SFQiao").GetSection("expressType").GetChildren();

            foreach (var item in expressTypes)
            {
                if (item["text"] == typeText)
                {
                    expressType = item.GetValue<int>("value");
                    break;
                }
            }
            #endregion
            dto.expressType = expressType;

            ///addedService				
            //   COD代收货款价值 单位元   此项和月结卡号绑定的增值服务相关
            //dto.codValue = "0.1";by hhg 0129
            //dto.codMonthAccount = ""; //代收货款卡号 -如有代收货款专用卡号必传

            if (!string.IsNullOrWhiteSpace(sFOrder.DeclaredValue))
                dto.insureValue = sFOrder.DeclaredValue; //声明保价价值  单位元

            dto.monthAccount = sFOrder.MonthlyCardNumber; //月结卡号
            dto.orderNo = sFOrder.Id + "";

            #region 付款方式
            var peyMethod = 1;
            var payText = sFOrder.PaymentMethod;
            var payMethods = _configurationRoot.GetSection("SFQiao").GetSection("payMethod").GetChildren();

            foreach (var item in payMethods)
            {
                if (payText.Contains(item["text"]))
                {
                    peyMethod = item.GetValue<int>("value");
                    break;
                }
            }
            #endregion
            dto.payMethod = peyMethod; // 1寄方付 2收方付 3第三方月结支付

            dto.childRemark = "";
            dto.mainRemark = sFOrder.Note1;
            dto.returnTrackingRemark = "";
            //dto.custLogo = "";
            //dto.logo = "";
            //dto.insureFee = "";
            //dto.payArea = "";
            //加密项
            dto.encryptCustName = true;//加密寄件人及收件人名称
            dto.encryptMobile = true;//加密寄件人及收件人联系手机	



            ArrayList rlsInfoDtoList = new ArrayList();


            RlsInfoDto rlsMain = new RlsInfoDto();
            rlsMain.abFlag = "A";
            //rlsMain.codingMapping = "F33";
            //rlsMain.codingMappingOut = "1A";
            rlsMain.destRouteLabel = orderResult.destRouteLabe;
            rlsMain.destTeamCode = orderResult.destTeamCode;
            rlsMain.printIcon = orderResult.printIcon;
            rlsMain.proCode = orderResult.proCode;
            rlsMain.qrcode = orderResult.twoDimensionCode;
            rlsMain.sourceTransferCode = orderResult.sourceTransferCode;
            rlsMain.waybillNo = orderResult.waybillNo;
            rlsMain.xbFlag = orderResult.xbFlag;
            rlsInfoDtoList.Add(rlsMain);

            if (null != dto.returnTrackingNo && 1 == 3)
            {
                RlsInfoDto rlsBack = new RlsInfoDto();
                rlsBack.waybillNo = dto.returnTrackingNo;
                rlsBack.destRouteLabel = "021WTF";
                rlsBack.printIcon = "11110000";
                rlsBack.proCode = "T4";
                rlsBack.abFlag = "A";
                rlsBack.xbFlag = "XB";
                rlsBack.codingMapping = "1A";
                rlsBack.codingMappingOut = "F33";
                rlsBack.destTeamCode = "87654321";
                rlsBack.sourceTransferCode = "755WE-571A3";
                //对应下订单设置路由标签返回字段twoDimensionCode 该参
                rlsBack.qrcode = "MMM={'k1':'21WT','k2':'755WE','k3':'','k4':'T4','k5':'443123456789','k6':''}";
                rlsInfoDtoList.Add(rlsBack);
            }




            CargoInfoDto cargo = new CargoInfoDto();
            cargo.cargo = sFOrder.ShippingNumber;
            cargo.cargoCount = Convert.ToInt32(sFOrder.Quantity);
            cargo.cargoUnit = "件";
            //cargo.sku = sFOrder.ShippingNumber;
            cargo.remark = sFOrder.Note1;

            CargoInfoDto cargo2 = new CargoInfoDto();
            cargo2.cargo = "苹果macbook pro";
            cargo2.cargoCount = 10;
            cargo2.cargoUnit = "件";
            cargo2.sku = "00015646";
            cargo2.remark = "笔记本贵重物品 小心轻放";

            ArrayList cargoInfoList = new ArrayList();
            //cargoInfoList.Add(cargo2);
            cargoInfoList.Add(cargo);

            dto.cargoInfoDtoList = cargoInfoList;
            dto.rlsInfoDtoList = rlsInfoDtoList;


            if (isFengMi)
            {
                dto.rlsInfoDtoList = rlsInfoDtoList;

            }

            waybillDtoList.Add(dto);

            return waybillDtoList;
        }

        private string AssemblyParameters( SFOrder sFOrder, Boolean isFengMi) 
        {
            return Newtonsoft.Json.JsonConvert.SerializeObject(GetAssemblyParameters(sFOrder,isFengMi));
        }

        //向服务传递参数
        private string postJson(string reqURL, string jsonParm)
        {

            string httpResult = "";
            try
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqURL);
                //req.ContentType = "application/json";
                //req.ContentType = "application/x-www-form-urlencoded";
                req.ContentType = "application/json;charset=utf-8";

                req.Method = "POST";
                req.Timeout = 20000;

                byte[] bs = System.Text.Encoding.UTF8.GetBytes(jsonParm);


                using (Stream reqStream = req.GetRequestStream())
                {
                    reqStream.Write(bs, 0, bs.Length);
                }

                using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
                {
                    //在这里对接收到的页面内容进行处理
                    using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.Default))
                    {
                        httpResult = sr.ReadToEnd().ToString();
                    }
                }


                if (httpResult.Contains("["))
                {
                    httpResult = httpResult.Substring(httpResult.IndexOf("[") + 1, httpResult.IndexOf("]") - httpResult.IndexOf("[") - 1);
                }

                if (httpResult.StartsWith("\""))
                {

                    httpResult = httpResult.Substring(1, httpResult.Length - 1);
                }
                if (httpResult.EndsWith("\""))
                {
                    httpResult = httpResult.Substring(0, httpResult.Length - 1);
                }

                // 将换行全部替换成空
                httpResult = httpResult.Replace("\\n", "");

            }
            catch (Exception ex)
            {
                return ex.Message;
            }

            return httpResult;
        }

        //将图片文件写入本地
        public Boolean generateImage(String imgStr, String imgFilePath)
        {
            if (imgStr == null)
                return false;
            try
            {

                byte[] bytes = Convert.FromBase64String(imgStr);


                int x = 256;
                byte a = (byte)x;

                for (int i = 0; i < bytes.Length; i++)
                {
                    if (bytes[i] < 0)
                    {
                        bytes[i] += a;
                    }
                }

                //FileStream write = File.OpenWrite(imgFilePath);

                using (FileStream fs = new FileStream(imgFilePath, FileMode.OpenOrCreate, FileAccess.Write))
                {
                    fs.Write(bytes, 0, bytes.Length);
                    //fs.Flush();

                    fs.Close();
                }


            }
            catch (Exception e)
            {
                return false;
            }
            return true;

        }

        public Task<List<WaybillDto>> GetWaybillPrintInfo(long orderId)
        {
            var order = _sfOrderRepository.Get(orderId);
            return Task.FromResult( GetAssemblyParameters(order, true).ToList());
        }


        #endregion



    }
}
